home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / pluginy Firefox / 11255 / 11255.xpi / chrome / content / model / Model.js < prev   
Text File  |  2009-12-17  |  23KB  |  591 lines

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * 
  3.  * Pearltrees add-on AMO, Copyright(C), 2009, Broceliand SAS, Paris, France 
  4.  * (company in charge of developing Pearltrees)
  5.  * 
  6.  * This file is part of ΓÇ£Pearltrees add-on AMOΓÇ¥.  
  7.  * 
  8.  * Pearltrees add-on AMO is free software: you can redistribute it and/or modify it under the 
  9.  * terms of the GNU General Public License version 3 as published by the Free Software Foundation.
  10.  * 
  11.  * Pearltrees add-on AMO is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 
  12.  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
  13.  * See the GNU General Public License for more details.
  14.  * 
  15.  * You should have received a copy of the GNU General Public License along with Pearltrees add-on AMO. 
  16.  * If not, see <http://www.gnu.org/licenses/>
  17.  * 
  18.  * ***** END LICENSE BLOCK ***** */
  19.  
  20. /////////////////////////////////////////////////////////////////////////////////
  21. // Model class
  22. // Handle server connections and password managers 
  23. //
  24. // Classes:
  25. //
  26. //    BRO_model  Communication with the server
  27. //    BRO_JSON   Handle JSON objects
  28. //
  29. /////////////////////////////////////////////////////////////////////////////////
  30.  
  31. /**
  32.  * Communication with the server.
  33.  */
  34. var BRO_model = {
  35.     
  36.     _json:null,
  37.     _serviceUrl:null,
  38.     
  39.     _treeList:null, // treeItem: treeID, title, pearlCount, lastUpdate
  40.     _historyList:null, // historyItem: id, name, pearlCount, lastUpdate
  41.     _currentUser:null, // user: userID, userDB, username, rootTreeID
  42.     
  43.     _skipNotificationIfNotLoggedOnNextValidation:false,
  44.     
  45.     getServiceUrl: function(){return this._serviceUrl},
  46.     
  47.     getTreeList: function(){return this._treeList},
  48.     setTreeList: function(value){this._treeList = value},
  49.  
  50.     getHistoryList: function(){return this._historyList},
  51.     setHistoryList: function(value){this._historyList = value},    
  52.     
  53.     getCurrentUser: function(){return this._currentUser},
  54.     setCurrentUser: function(value){this._currentUser = value},    
  55.     
  56.     getRootTree: function () {
  57.         if(!this._treeList || !this._currentUser) return null;
  58.         
  59.         var treeListLength = this._treeList.length;
  60.         
  61.         for (var i = 0; i < treeListLength; i++) {
  62.             if (this._treeList[i].treeID == this._currentUser.rootTreeID) {             
  63.                 return this._treeList[i];
  64.             }
  65.         }
  66.         return null;
  67.     },
  68.     
  69.     START_HISTORY_SUCCESS:0,
  70.     START_HISTORY_SUCCESS_ON_SWITCH:1,
  71.     START_HISTORY_ERROR_INVALID_TREE:2,
  72.     START_HISTORY_ERROR_TREE_DELETED:3,
  73.     START_HISTORY_ERROR_IS_NOT_OWNER:4,    
  74.      
  75.     skipNextRequestValidation:false,
  76.     
  77.     /**
  78.      * Init server connection parameters
  79.      * @todo Should be moved in a config file
  80.      */
  81.     init: function() {      
  82.         this._treeList = null;
  83.         this._historyList = null;
  84.         this._currentUser = null;
  85.         this._serviceUrl = BRO_SERVICE_FF_URL;
  86.         
  87.         // Try to use FF3 native json component
  88.         if(Components.classes["@mozilla.org/dom/json;1"]) {
  89.             this._json = Components.classes["@mozilla.org/dom/json;1"]
  90.                          .createInstance(Components.interfaces.nsIJSON);
  91.         }else{
  92.             this._json = JSONFF2;
  93.         }
  94.     },
  95.     
  96.     /**
  97.      * Create a GET XMLHttpRequest object with a valid cookie.
  98.      * @param string url
  99.      * @return XMLHttpRequest
  100.      */
  101.     createXMLHttpRequest:function(url) {       
  102.         var req = new XMLHttpRequest();
  103.         req.open('GET', url, true);
  104.  
  105.         return req;
  106.     },
  107.     
  108.     notifyDownloadToAMO:function() {
  109.         var url = BRO_AMO_FILE_URL + "?src=" + BRO_AMO_SOURCE;
  110.         
  111.         var req = this.createXMLHttpRequest(url);
  112.         
  113.         req.onreadystatechange = function (e) {
  114.             if (req.readyState == 4) {
  115.                 BRO_toolbar.onDownloadNotifiedToAMO();
  116.             }            
  117.         }   
  118.         req.send(null);        
  119.     },
  120.     
  121.     notifyActiveUserToAMO:function() {
  122.         var extension = Components.classes["@mozilla.org/extensions/manager;1"]
  123.                                 .getService(Components.interfaces.nsIExtensionManager)       
  124.                                 .getItemForID(BRO_ADDON_ID);
  125.         var appInfo = Components.classes["@mozilla.org/xre/app-info;1"]
  126.                                 .getService(Components.interfaces.nsIXULAppInfo);        
  127.         var xulRuntime = Components.classes["@mozilla.org/xre/app-info;1"]
  128.                                    .getService(Components.interfaces.nsIXULRuntime);        
  129.         var useragentPrefs = Components.classes["@mozilla.org/preferences-service;1"]
  130.                              .getService(Components.interfaces.nsIPrefService)
  131.                              .getBranch("general.useragent.");
  132.                                 
  133.         var reqVersion = "%"; // request last version
  134.         var version = extension.version; // current addon version (e.g: 5.0.9)
  135.         var id = extension.id; // addon id (e.g: collector@broceliand.fr)
  136.         var appID = appInfo.ID; // Firefox Application ID
  137.         var appVersion = appInfo.version; // Firefox version (e.g: 3.6b4)    
  138.         var locale = useragentPrefs.getCharPref("locale"); // lang (e.g: en_US)
  139.         var appOS = xulRuntime.OS; // OS family (e.g: WINNT)
  140.         var appABI = xulRuntime.XPCOMABI; // compiler info
  141.         var maxAppVersion = extension.maxAppVersion; // addon max version supported
  142.         var status = "userEnabled"; // is the addon enabled
  143.         if(typeof(Application) != 'undefined') {
  144.             var extensions = Application.extensions.all;
  145.             for(var i=0; i<extensions.length; i++) {
  146.                 var ext = extensions[i];
  147.                 if(ext.id == id) {
  148.                     status = (ext.enabled)?"userEnabled":"userDisabled";
  149.                 }
  150.             }
  151.         }        
  152.         
  153.         var url = BRO_AMO_VERSION_CHECK +
  154.                   "?reqVersion="+reqVersion+
  155.                   "&version="+version+
  156.                   "&id="+id+
  157.                   "&appID="+appID+
  158.                   "&appVersion="+appVersion+
  159.                   "&locale="+locale+
  160.                   "&appOS="+appOS+
  161.                   "&appABI="+appABI+
  162.                   "&maxAppVersion="+maxAppVersion+
  163.                   "&status="+status;
  164.         
  165.         var req = this.createXMLHttpRequest(url);      
  166.         
  167.         req.onreadystatechange = function (e) {
  168.             if (req.readyState == 4) {
  169.                 BRO_toolbar.onActiveUserNotifiedToAMO();
  170.             }            
  171.         }   
  172.         req.send(null);                  
  173.     },
  174.     
  175.     /**
  176.      * Start a new history
  177.      */
  178.     start:function(newTreeName) {
  179.         var action = 'start';
  180.         var params = '?newTreeName='+newTreeName
  181.                     +'&time='+BRO_tools.getTime();
  182.         
  183.         BRO_log.log('start new history ('+newTreeName+')');
  184.         
  185.         var req = this.createXMLHttpRequest(this._serviceUrl+action+params);
  186.  
  187.         req.onreadystatechange = function (e) {
  188.         if (req.readyState == 4) {
  189.             if(BRO_model.validateResponse(req,true)) {
  190.                 if(req.responseText) {                   
  191.                     //BRO_log.log('Started !'+req.responseText);
  192.                 }
  193.             }
  194.         };}   
  195.         req.send(null);
  196.     },
  197.     
  198.     /**
  199.      * continue an existing history
  200.      */
  201.     continueHistory:function(treeID, historyID) {
  202.         var action = 'continue';
  203.         var params = '?time='+BRO_tools.getTime()
  204.                     +'&treeID='+treeID
  205.                     +'&historyID='+historyID;
  206.        
  207.         BRO_log.log('continue history ('+treeID+', '+historyID+')'); 
  208.         
  209.         var req = this.createXMLHttpRequest(this._serviceUrl+action+params);
  210.  
  211.         req.onreadystatechange = function (e) {
  212.         if (req.readyState == 4) {
  213.             if(BRO_model.validateResponse(req,true) && req.responseText) {
  214.                 if(req.responseText == BRO_model.START_HISTORY_ERROR_TREE_DELETED) {
  215.                     BRO_toolbar.showTreeDeletedMessage();
  216.                 }else if(req.responseText != BRO_model.START_HISTORY_SUCCESS) {
  217.                     BRO_toolbar.errorOnContinueHistory(req.responseText);
  218.                 }
  219.             }
  220.         };}   
  221.         req.send(null);
  222.     },    
  223.     
  224.     addComment:function(url, browserUID, time, comment) {
  225.         
  226.         var action = 'addcomment';
  227.         var params = '?url='+encodeURIComponent(url)
  228.                     +'&browserUID='+browserUID
  229.                     +'&time='+time
  230.                     +'&comment='+comment;
  231.         
  232.         BRO_log.log('add comment ('+url+', '+browserUID+', '+time+', '+comment+')');
  233.         
  234.         var req = this.createXMLHttpRequest(this._serviceUrl+action+params);
  235.  
  236.         req.onreadystatechange = function (e) {
  237.         if (req.readyState == 4) {
  238.             BRO_model.validateResponse(req,true);
  239.         };}
  240.         req.send(null);
  241.     },
  242.     
  243.     /**
  244.      * Add a new pearl
  245.      */
  246.     add:function(url, title, method, browserUID, time, isStart, treeID, newTreeName, historyID) {
  247.         var action = 'add';
  248.         var title = encodeURIComponent(title.replace(/^\s*|\s*$/g,''));
  249.         var treeID = (!isStart && BRO_inButtonController._selectedTree)?BRO_inButtonController._selectedTree.treeID:null;
  250.         var historyID = (!isStart && BRO_inButtonController._selectedHistory)?BRO_inButtonController._selectedHistory.id:null;
  251.         
  252.         var params = '?url='+encodeURIComponent(url)
  253.                     +'&title='+title
  254.                     +'&method='+method
  255.                     +'&browserUID='+browserUID
  256.                     +'&time='+time;
  257.         if(isStart) { 
  258.             params += '&isStart='+isStart;
  259.             params += '&newTreeName='+newTreeName;
  260.         }
  261.         if(treeID) params += '&treeID='+treeID;
  262.         if(historyID) params += '&historyID='+historyID;
  263.         
  264.         // If the method sent will create a pearl we run an effect
  265.         // @todo run the effect on server response
  266.         if(method != BRO_METHOD_TAB_CREATED) {
  267.             BRO_buttonEffectHelper.runIsRecordingEffect();
  268.         }
  269.         
  270.         BRO_log.log('add ('+url+', '+title+', '+method+' , '+browserUID+ ', '+time+', '+isStart+', '+treeID+', '+newTreeName+', '+historyID+')');            
  271.         
  272.         var req = this.createXMLHttpRequest(this._serviceUrl+action+params);
  273.         
  274.         req.onreadystatechange = function (e) {
  275.         if (req.readyState == 4) {
  276.             if(BRO_model.validateResponse(req,true) && req.responseText) {
  277.                 // If recording in a deleted tree
  278.                 if(req.responseText == BRO_model.START_HISTORY_ERROR_TREE_DELETED) {
  279.                     BRO_toolbar.showTreeDeletedMessage();
  280.                 }
  281.                 // If a server error occured
  282.                 else if(req.responseText != BRO_model.START_HISTORY_SUCCESS && req.responseText != BRO_model.START_HISTORY_SUCCESS_ON_SWITCH) {
  283.                     BRO_toolbar.errorOnContinueHistory(req.responseText);
  284.                 }
  285.             }
  286.         };}
  287.         req.send(null);
  288.     },
  289.     
  290.     /**
  291.      * Validate URLs for inserts
  292.      * @param string url
  293.      */
  294.     isValidUrl:function(url) {
  295.         if(!url
  296.              || url == ''
  297.              || url == 'about:blank' 
  298.              || url.lastIndexOf(BRO_PUBLIC_URL) == 0
  299.              || url.lastIndexOf('http://www.broceliand.fr') ==0
  300.              || (url.lastIndexOf('http://www.pearltrees.com') ==0 
  301.                  && url.lastIndexOf('http://www.pearltrees.com/blog') == -1
  302.                  && url.lastIndexOf('http://www.pearltrees.com/forum') == -1)
  303.              || url.lastIndexOf('http://localhost') ==0
  304.              || url.lastIndexOf('http://127.0.0.1') ==0
  305.              || url.substring(0,4) != 'http'){  
  306.            return false;
  307.         }
  308.         return true;
  309.     },
  310.     
  311.     /**
  312.      * Clear the current history if exist.
  313.      * Called when the application stop.
  314.      */
  315.     clear:function() {
  316.         var action = 'clear';
  317.         var params = '?time='+BRO_tools.getTime(); 
  318.         
  319.         BRO_log.log('clear');
  320.         
  321.         var req = this.createXMLHttpRequest(this._serviceUrl+action+params);
  322.         
  323.         req.onreadystatechange = function (e) {
  324.             if (e && e.readyState == 4) {
  325.                 //...
  326.             };
  327.         }        
  328.         req.send(null);
  329.     },
  330.     
  331.     getTreesAndCurrentUser:function(skipNotificationIfNotLogged) {
  332.         var action = 'gettreesandcurrentuser';
  333.         var params = '';
  334.         
  335.         this._skipNotificationIfNotLoggedOnNextValidation = skipNotificationIfNotLogged;
  336.         BRO_log.log('load trees and current user');
  337.         
  338.         var req = this.createXMLHttpRequest(this._serviceUrl+action+params);
  339.  
  340.         req.onreadystatechange = function (e) {
  341.             if (req.readyState == 4) {
  342.                 if(BRO_model.validateResponse(req)) {
  343.                     if (req.responseText) {
  344.                         var response = BRO_model._json.decode(req.responseText);
  345.                         
  346.                         var currentUserResponse = response.currentUser;
  347.                         BRO_model.updateCurrentUser(currentUserResponse);                        
  348.                         
  349.                         var listChanged = false;
  350.                         var treeListResponse = response.treeList;
  351.                         var historyListResponse = response.historyList;                    
  352.                         
  353.                         if(!BRO_model._treeList || !BRO_model.areTreeListsEquals(treeListResponse,BRO_model._treeList)) {                        
  354.                             BRO_model._treeList = BRO_model.mergeLocalTreeListWithServerList(treeListResponse);
  355.                             BRO_windowManager.setTreeList(BRO_model._treeList);
  356.                             // must be called after currentUser being set
  357.                             BRO_toolbar.saveRootTreeIntoPreferences(BRO_model.getRootTreeFromTreeList());
  358.                             BRO_toolbar.saveDropZoneIntoPreferences(BRO_model.getDropZoneFromTreeList());
  359.                             listChanged = true;
  360.                         }
  361.                         
  362.                         if(!BRO_model._historyList || !BRO_model.areHistoryListsEquals(historyListResponse,BRO_model._historyList)) {
  363.                             BRO_model._historyList = BRO_model.mergeLocalHistoryListWithServerList(historyListResponse);    
  364.                             BRO_windowManager.setHistoryList(BRO_model._historyList);
  365.                             listChanged = true;
  366.                         }
  367.                         
  368.                         if(listChanged) {
  369.                             BRO_inButtonController.onTreeListLoaded();
  370.                         }
  371.                         else{
  372.                             BRO_inButtonController.onTreeListNotChanged();
  373.                         }
  374.                     }
  375.                 }
  376.             }
  377.         }
  378.         req.send(null);
  379.     }, 
  380.     
  381.     getRootTreeFromTreeList:function() {
  382.         var treeList = BRO_model.getTreeList();
  383.         var currentUser = BRO_model.getCurrentUser();
  384.         if(!treeList || !currentUser) return;
  385.         
  386.         for(var i=0; i < treeList.length; i++) {        
  387.             if(treeList[i].treeID == currentUser.rootTreeID) {
  388.                 return treeList[i];
  389.             }
  390.         }
  391.         return null;
  392.     },
  393.     
  394.     getDropZoneFromTreeList:function() {
  395.         var treeList = BRO_model.getTreeList();
  396.         var currentUser = BRO_model.getCurrentUser();
  397.         if(!treeList || !currentUser) return;
  398.         
  399.         for(var i=0; i < treeList.length; i++) {        
  400.             if(treeList[i].treeID == currentUser.dropZoneID) {
  401.                 return treeList[i];
  402.             }
  403.         }
  404.         return null;
  405.     },    
  406.     
  407.     updateCurrentUser:function(value) {
  408.         if(!BRO_model.areUserEquals(value, BRO_model._currentUser)) {               
  409.             BRO_model._currentUser = value;
  410.             BRO_windowManager.setCurrentUser(BRO_model._currentUser);
  411.             if(BRO_model._currentUser) {
  412.                 BRO_toolbar.saveCurrentUserIntoPreferences(BRO_model._currentUser);
  413.             }
  414.         }
  415.         if(BRO_toolbar.getOptionWindow() && BRO_toolbar.getOptionWindow().document) {
  416.             var statusDescription = BRO_toolbar.getOptionWindow().document.getElementById('BRO_statusDescription');
  417.             if(statusDescription) {
  418.                 if(BRO_toolbar.isUserLogged && BRO_model._currentUser) {
  419.                     statusDescription.value = "signed as "+BRO_model._currentUser.username;
  420.                 }else{
  421.                     statusDescription.value = "signed out";
  422.                 }
  423.             }
  424.         }
  425.     },
  426.     
  427.     areTreeListsEquals:function(list1, list2) {
  428.         if(!list1 && !list2) return true;
  429.         if((!list1 && list2) || (list1 && !list2)) return false;
  430.         var list1Length = list1.length;
  431.         var list2Length = list2.length;
  432.         if(list1Length != list2Length) return false;
  433.         
  434.         for(var i=0; i < list1Length;i++) {            
  435.             if(list1[i].treeID != list2[i].treeID) {
  436.                 return false;
  437.             }
  438.             else if(list1[i].title != list2[i].title) {
  439.                 return false;
  440.             }
  441.             else if(list1[i].lastUpdate != list2[i].lastUpdate) {              
  442.                return false;
  443.             }
  444.         }
  445.         return true;
  446.     },
  447.     
  448.     mergeLocalTreeListWithServerList:function(serverTreeList) {
  449.         var localTreeList = BRO_model._treeList;
  450.         
  451.         if(!localTreeList) return serverTreeList;
  452.         if(!serverTreeList) return null;
  453.         var serverTreeListLength = serverTreeList.length;
  454.         var localTreeListLength = localTreeList.length;
  455.         
  456.         // Don't update trees if we don't need to
  457.         for(var i=0; i < serverTreeListLength; i++) {
  458.             for(var j=0; j < localTreeListLength; j++) {
  459.                 if(serverTreeList[i].treeID == localTreeList[j].treeID
  460.                    && serverTreeList[i].title == localTreeList[j].title
  461.                    && serverTreeList[i].lastUpdate == localTreeList[j].lastUpdate) {
  462.                    
  463.                    serverTreeList[i] = localTreeList[j];
  464.                    break;
  465.                 }
  466.             }
  467.         }
  468.         
  469.         return serverTreeList;
  470.     },
  471.     
  472.     mergeLocalHistoryListWithServerList:function(serverHistoryList) {
  473.         var localHistoryList = BRO_model._treeList;
  474.         
  475.         if(!localHistoryList) return serverHistoryList;
  476.         if(!serverHistoryList) return null;
  477.         var serverHistoryListLength = serverHistoryList.length;
  478.         var localHistoryListLength = localHistoryList.length;
  479.         
  480.         // Don't update trees if we don't need to
  481.         for(var i=0; i < serverHistoryListLength; i++) {
  482.             for(var j=0; j < localHistoryListLength; j++) {
  483.                 if(serverHistoryList[i].id == localHistoryList[j].id
  484.                    && serverHistoryList[i].name == localHistoryList[j].name
  485.                    && serverHistoryList[i].lastUpdate == localHistoryList[j].lastUpdate) {
  486.                    
  487.                    serverHistoryList[i] = localHistoryList[j];
  488.                    break;
  489.                 }
  490.             }
  491.         }
  492.         
  493.         return serverHistoryList;
  494.     },    
  495.     
  496.     areHistoryListsEquals:function(list1, list2) {
  497.         if(!list1 && !list2) return true;
  498.         if((!list1 && list2) || (list1 && !list2)) return false;        
  499.         var list1Length = list1.length;
  500.         var list2Length = list2.length;
  501.         if(list1Length != list2Length) return false;
  502.         
  503.         for(var i=0; i < list1Length;i++) {            
  504.             if(list1[i].id != list2[i].id || list1[i].name != list2[i].name) return false;
  505.         }
  506.         return true;
  507.     },    
  508.     
  509.     areUserEquals:function(user1, user2) {
  510.         if(!user1 && !user2) return true;
  511.         if((!user1 && user2) || (user1 && !user2)) return false;        
  512.         return (user1.userID == user2.userID)?true:false;
  513.     },
  514.     
  515.     /**
  516.      * Validate XMLHttpRequest reponse and handle errors
  517.      * @param resp XMLHttpRequest response
  518.      */
  519.     validateResponse:function(resp, retryOnError) {
  520.         if(!resp) return false;
  521.         var status = null;
  522.         var responseText = null;
  523.         try{
  524.            status = resp.status;
  525.            responseText = resp.responseText;
  526.         }
  527.         catch(e){}
  528.  
  529.         // Valid
  530.         if(status == 200 || this.skipNextRequestValidation) {
  531.             this.skipNextRequestValidation = false;
  532.             BRO_toolbar.isUserLogged = true;
  533.             return true;
  534.         }
  535.         // No session auth is opened.
  536.         else if(status == 303) {
  537.             BRO_log.log("server 303 Not Logged");
  538.             BRO_toolbar.isUserLogged = false;
  539.             // Stop all recording actions.
  540.             BRO_toolbar.setRecording(false);
  541.             if(!BRO_toolbar.isThirdPartyCookiesEnabled()) {
  542.                 if(BRO_toolbar.isUserWantToEnableThirdPartyCookies()){
  543.                     BRO_toolbar.enableThirdPartyCookies();
  544.                     if(retryOnError) BRO_ButtonsHandler.startRecording();
  545.                 }
  546.             }
  547.             else if(!this._skipNotificationIfNotLoggedOnNextValidation) {
  548.                 if(BRO_toolbar.isUserWantToLogin()==true) {
  549.                     BRO_toolbar.showLoginForm();
  550.                 }
  551.             }
  552.             BRO_model.resetModel();
  553.         }
  554.         // Unauthorized WWW-Authenticate
  555.         else if(status == 401){
  556.             if(BRO_toolbar.isRecording) {
  557.                 BRO_toolbar.setRecording(false);
  558.             }
  559.         }
  560.         else {
  561.             BRO_log.log("Invalid server response. HTTP status: "+status+" "+responseText);
  562.             BRO_log.error(BRO_locale.getString('popup.error.responseError'));
  563.         }
  564.         this.skipNextRequestValidation = false;
  565.         return false;
  566.     },
  567.     
  568.     // @todo refactor
  569.     resetModel:function() {
  570.         // update model
  571.         BRO_model.updateCurrentUser(null);  
  572.         
  573.         BRO_model.setTreeList(null);       
  574.         BRO_windowManager.setTreeList(null);  
  575.         
  576.         BRO_model.setHistoryList(null);
  577.         BRO_windowManager.setHistoryList(null);         
  578.         
  579.         // update toolbar state
  580.         BRO_toolbar.setRecording(false);
  581.         
  582.         // update ButtonsHandler
  583.         BRO_inButtonController._selectedTree = null;
  584.         BRO_inButtonController._selectedHistory = null;
  585.         BRO_inButtonController._selectedNewHistory = null;
  586.  
  587.         BRO_inButtonController.initTreeList();
  588.         BRO_toolbar.lastUrlRecorded = null;
  589.         BRO_recordButtonController.refreshRecordButtonLabel(BRO_toolbar.isRecording);
  590.     }
  591. }